<?php

abstract class Connection implements DatabaseConnection
{
    const prfx = '?pre';
    protected $_praefix = '';
    
    protected $_getAllIndex = 'id';
    
    /**
     * Querycount
     * @var integer
     */
    protected $_queryCount = 0;
    
    /**
     * Magic Quotes
     * @var boolean
     */
    protected $_MQ = false;
    
    /**
     * Connection
     * @var Resource
     */
    protected $_connection = NULL;
    
     /**
     * Get the Connectionresource
     *
     * @return Connection
     */
    protected function _getConnection()
    {
        if ($this->_connection === NULL) {
            $this->_connect();
        }
        return $this->_connection;
    }
    
    public function queryCount()
    {
        return $this->_queryCount;
    }
    
    abstract protected function _connect();
    
    /**
     * Cloning not allowed! Resource(handler).
     * @throws DBException
     */
    public final function __clone()
    {
        throw new DBException('A resource cannot be cloned!');
    }
    
    public function __construct()
    {
        $this->_MQ = (get_magic_quotes_gpc() == 1) ? true : false;
    }
    public function query($sql) {
        $this->_queryCount++;
        return $this->_getConnection()->query($this->replacePraefix($sql));
    }
    
    public function replacePraefix($sql)
    {
        return str_replace(self::prfx, $this->_praefix, $sql);
    }
    
    public function setReplacePraefix($string)
    {
        #if (empty($string)) {
        #    throw new DBException('Connection: empty replace praefix given!');
        #}
        $this->_praefix = (string) $string;
    }
    
    protected function _setConnection($conn)
    {
        if (!is_object($conn)) {
            throw new DBException('Connection: non-object given, resource expected!');
        }
        $this->_connection = $conn;
    }
    
    #abstract public function escape($sql);
    
    
    public function prepare($sql, $types = NULL) {
        $this->_queryCount++;
        return $this->_getConnection()->prepare($this->replacePraefix($sql), $types);
    }
    
    public function close()
    {
        $this->_connection->close();
    }
    
    public function getAllIndex($modifyTo)
    {
        $this->_getAllIndex = is_string($modifyTo) ? $modifyTo : false;
    }
    
    public function getAll($sql)
    {
        $res = $this->query($sql);
        if (! is_object($res)) {
            return false;
        }
        $ret = array();
        while ($row = $res->fetchAssoc())
        {
            if ($this->_getAllIndex && isset($row[$this->_getAllIndex]))
            {
                $ret[$row[$this->_getAllIndex]] = $row;
            }
            else
            {
                $ret[] = $row;
            }
        }
        $res->free();
        return $ret;
    }
    
    public function getOne($sql)
    {
        if (! $res = $this->query($sql) ) {
            return false;
        }
        $row = $res->fetchAssoc();
        $res->free();
        return $row;
    }
    
    public function sqlSelect($table, $where = '', $all = true, $select = '*')
    {
        if (empty($table)) {
            throw new SQLException('Invalid parameter [table]');
        }
        return $all
            ? $this->getAll('SELECT '.$select.' FROM '.$this->_praefix.$table.$where)
            : $this->getOne('SELECT '.$select.' FROM '.$this->_praefix.$table.$where);
    }
    
    public function sqlUpdate($table, array $update, $where = '', $escape = true) 
    {
        if (empty($table))  {
            throw new DBException('Invalid parameter [table]');
        }
        if (empty($update)) {
            return false;
        }
        $s = array();
        foreach($update as $key => $val) {
            $s[] = sprintf("`%s` = '%s'",
                $key,
                $escape ? $this->escape($val) : $val
            );
        }
        $sql = sprintf("UPDATE `%s` SET %s %s",
                    $this->_praefix.$table,
                    implode(',', $s),
                    $where);
        return $this->query($sql);
    }
}
